// Kony


#include "Character/BaseCharacter.h"
#include "AbilitySystemComponent.h"
#include "BaseGameplayTags.h"
#include "AbilitySystem/BaseAbilitySystemComponent.h"
#include "AbilitySystem/Debuff/DebuffNiagaraComponent.h"
#include "AbilitySystem/Passive/PassiveNiagaraComponent.h"
#include "Component/TargetLockComponent.h"
#include "Components/CapsuleComponent.h"
#include "Components/SphereComponent.h"
#include "Components/WidgetComponent.h"
#include "GASC_HuanLing/GASC_HuanLing.h"
#include "Kismet/GameplayStatics.h"
#include "GameFramework/CharacterMovementComponent.h"
#include "Net/UnrealNetwork.h"

//角色基类
ABaseCharacter::ABaseCharacter()
{
	//启用TICK
	PrimaryActorTick.bCanEverTick = true;
	//创建目标锁定组件
	TargetLockComponent = CreateDefaultSubobject<UTargetLockComponent>(TEXT("TargetLockComponent"));
	// TargetLockComponent->SetupAttachment(GetRootComponent());

	/* 创建异常粒子组件 start */
	//创建燃烧异常效果组件
	BurnDebuffComponent = CreateDefaultSubobject<UDebuffNiagaraComponent>("BurnDebuffComponent");
	BurnDebuffComponent->SetupAttachment(GetRootComponent());
	BurnDebuffComponent->DebuffTag = FBaseGameplayTags::Get().Debuff_Propertie_Burn;
	//创建眩晕异常效果组件
	StunDebuffComponent = CreateDefaultSubobject<UDebuffNiagaraComponent>("StunDebuffComponent");
	StunDebuffComponent->SetupAttachment(GetRootComponent());
	StunDebuffComponent->DebuffTag = FBaseGameplayTags::Get().Debuff_Propertie_Stun;
	/* 创建异常粒子组件 end */ 
	//设置摄像机碰撞不对角色进行影响
	GetCapsuleComponent()->SetCollisionResponseToChannel(ECC_Camera, ECR_Ignore);
	GetCapsuleComponent()->SetCollisionResponseToChannel(ECC_Projectile, ECR_Overlap);
	//设置胶囊体不碰撞，这个主要是避免和网格重复，暂定用网格 这样更精细
	GetCapsuleComponent()->SetGenerateOverlapEvents(false);
	//设置网格机碰撞不对角色进行影响
	GetMesh()->SetCollisionResponseToChannel(ECC_Camera, ECR_Ignore);
	//设置网格重叠事件 ,不能设置这个 因为角色是用胶囊体进行碰撞，如果设置这个就会冲突
	GetMesh()->SetGenerateOverlapEvents(true);
	//与投射物重叠
	GetMesh()->SetCollisionResponseToChannel(ECC_Projectile, ECR_Overlap);

	//创建武器组件
	Weapon = CreateDefaultSubobject<USkeletalMeshComponent>("Weapon");
	//设置武器 附加到角色网格体
	Weapon->SetupAttachment(GetMesh(), FName("WeaponHandSocket"));
	//设置武器 禁用碰撞
	Weapon->SetCollisionEnabled(ECollisionEnabled::NoCollision);
	//头顶血条
	HealthBar = CreateDefaultSubobject<UWidgetComponent>("HealthBar");
	//血条添加到跟组件
	HealthBar->SetupAttachment(GetRootComponent());

	//创建效果附加组件
	EffectAttachComponent = CreateDefaultSubobject<USceneComponent>("EffectAttachComponent");
	EffectAttachComponent->SetupAttachment(GetRootComponent());
	/* 创建被动粒子组件 附加到效果组件 start */
	//护盾
	HaloOfProtectionNiagaraComponent = CreateDefaultSubobject<UPassiveNiagaraComponent>("HaloOfProtectionNiagaraComponent");
	HaloOfProtectionNiagaraComponent->SetupAttachment(EffectAttachComponent);
	//生命汲取
	LifeSiphonNiagaraComponent = CreateDefaultSubobject<UPassiveNiagaraComponent>("LifeSiphonNiagaraComponent");
	LifeSiphonNiagaraComponent->SetupAttachment(EffectAttachComponent);
	//法力汲取
	ManaSiphonNiagaraComponent = CreateDefaultSubobject<UPassiveNiagaraComponent>("ManaSiphonNiagaraComponent");
	ManaSiphonNiagaraComponent->SetupAttachment(EffectAttachComponent);
	/* 创建被动粒子组件 添加到效果组件 end */

	//创建探查球体组件
	DetectionSphere = CreateDefaultSubobject<USphereComponent>("DetectionSphere");
	DetectionSphere->SetupAttachment(GetRootComponent());
	DetectionSphere->SetSphereRadius(300.0f);
	DetectionSphere->SetCollisionEnabled(ECollisionEnabled::QueryOnly);
	DetectionSphere->SetCollisionObjectType(ECC_Detection);
	DetectionSphere->SetCollisionResponseToAllChannels(ECR_Ignore);
	DetectionSphere->SetCollisionResponseToChannel(ECC_Pawn, ECR_Overlap);
}

void ABaseCharacter::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);
	//设置效果附加组件的世界旋转为0
	EffectAttachComponent->SetWorldRotation(FRotator::ZeroRotator);
}

void ABaseCharacter::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
	Super::GetLifetimeReplicatedProps(OutLifetimeProps);

	//复制异常效果部分
	DOREPLIFETIME(ABaseCharacter, bIsBurn); //燃烧
	DOREPLIFETIME(ABaseCharacter, bIsStunned); //眩晕
	DOREPLIFETIME(ABaseCharacter, bIsDown); //击倒
	DOREPLIFETIME(ABaseCharacter, bIsCrouching); //蹲伏
	DOREPLIFETIME(ABaseCharacter, bIsBeingShocked); //持续被电击
}

UAbilitySystemComponent* ABaseCharacter::GetAbilitySystemComponent() const
{
	return AbilitySystemComponent;
}
//受到伤害
float ABaseCharacter::TakeDamage(float DamageAmount, struct FDamageEvent const& DamageEvent, class AController* EventInstigator, AActor* DamageCauser)
{
	const float DamageTaken = Super::TakeDamage(DamageAmount, DamageEvent, EventInstigator, DamageCauser);
	//广播通过能力系统计算的伤害（用于在自定义的伤害计算中获取伤害计算实际伤害）
	OnDamageDelegate.Broadcast(DamageTaken);
	return DamageTaken;
}

//受击反馈
UAnimMontage* ABaseCharacter::GetHitReactMontage_Implementation()
{
	return HitReactMontage;
}
//仅在服务器调用濒死函数
void ABaseCharacter::Die(const FVector& DeathImpulse)
{
	//武器分离掉落处理,服务器执行了这个操作，客户端就不需要重复执行
	Weapon->DetachFromComponent(FDetachmentTransformRules(EDetachmentRule::KeepWorld, true));
	MulticastHandleDeath(DeathImpulse);
}
//获取是否死亡，主要用于判断范围内获取到的角色是否死亡
bool ABaseCharacter::IsDead_Implementation() const
{
	return bDead;
}
//获取角色化身，主要用于判断范围内获取角色 释放技能
AActor* ABaseCharacter::GetAvatar_Implementation()
{
	return this;
}
//蒙太奇攻击动画数组，用于获取攻击动画，可以用来做连续攻击或者左右手攻击动画的 顺序|随机播放
TArray<FTaggedMontage> ABaseCharacter::GetAttackMontages_Implementation()
{
	return AttackMontages;
}

UNiagaraSystem* ABaseCharacter::GetHitBloodEffect_Implementation()
{
	return HitBloodEffect;
}
//重写通过标签TAG返回TaggedMontage结构体，用于在Gameplay Cue 提示通过标签获取到蒙太奇和声音
FTaggedMontage ABaseCharacter::GetTaggedMontageByTag_Implementation(const FGameplayTag& MontageTag)
{
	for (const FTaggedMontage TaggedMontage : AttackMontages)
	{
		if (TaggedMontage.MontageTag == MontageTag)
		{
			return TaggedMontage;
		}
	}
	return FTaggedMontage();
}

int32 ABaseCharacter::GetMinionCount_Implementation()
{
	return MinionCount;
}
//重写写入当前召唤随从数量 传入正就是递增，传入负就是递减
void ABaseCharacter::IncremenetMinionCount_Implementation(int32 Amount)
{
	MinionCount += Amount;
}
//重写获取怪物职业
ECharacterClass ABaseCharacter::GetCharacterClass_Implementation()
{
	return CharacterClass;
}
//重写显示目标锁定光圈
void ABaseCharacter::ShowTargetIndicator_Implementation()
{
	if (TargetLockComponent)
	{
		TargetLockComponent->ShowTargetIndicator();
	}
}

void ABaseCharacter::HideTargetIndicator_Implementation()
{
	if (TargetLockComponent)
	{
		TargetLockComponent->HideTargetIndicator();
	}
}
//重写获取能力系统组件生效时广播委托
FOnASCRegistered& ABaseCharacter::GetOnASCRegisteredDelegate()
{
	return OnAscRegistered;
}
//重写获取死亡委托
FOnDeathSignature& ABaseCharacter::GetOnDeathDelegate()
{
	return OnDeathDelegate;
}
//重写受到伤害委托
FOnDamageSignature& ABaseCharacter::GetOnDamageSignature()
{
	return OnDamageDelegate;
}

//重写获取插槽组件函数,用于获取武器插槽等 角色身上的插槽
USkeletalMeshComponent* ABaseCharacter::GetSocketComponent_Implementation(const FString& SocketName)
{
	//判断如果 SocketName 等于 Weapon 或者 等于 空 返回  Weapon
	if (SocketName == "Weapon" || SocketName.IsEmpty())
	{
		return Weapon;
	}
	return Weapon;
}
//设置持续被电击
void ABaseCharacter::SetIsBeingShocked_Implementation(bool bInShock)
{
	bIsBeingShocked = bInShock;
}
//是否正在持续被电击
bool ABaseCharacter::IsBeingShocked_Implementation() const
{
	return bIsBeingShocked;
}

//多播广播处理濒死 用于服务端和客户端处理
void ABaseCharacter::MulticastHandleDeath_Implementation(const FVector& DeathImpulse)
{
	//播放死亡音效
	UGameplayStatics::PlaySoundAtLocation(this, DeathSound, GetActorLocation(),GetActorRotation());
	//客户端 设置武器掉落
	Weapon->SetSimulatePhysics(true);
	Weapon->SetEnableGravity(true);
	//设置武器碰撞 仅使用物理模拟，这个如果以后不用可以去掉
	Weapon->SetCollisionEnabled(ECollisionEnabled::PhysicsOnly);
	//给武器增加死亡被打的冲击力
	Weapon->AddImpulse(DeathImpulse * 0.1f, NAME_None, true);
	
	//设置网格体呈现布娃娃效果
	GetMesh()->SetSimulatePhysics(true);
	GetMesh()->SetEnableGravity(true);
	GetMesh()->SetCollisionEnabled(ECollisionEnabled::PhysicsOnly);
	GetMesh()->SetCollisionResponseToChannel(ECC_WorldStatic, ECR_Block);
	//给角色网格增加死亡被打的冲击力
	GetMesh()->AddImpulse(DeathImpulse, NAME_None, true);
	//设置胶囊体并禁用碰撞
	GetCapsuleComponent()->SetCollisionEnabled(ECollisionEnabled::NoCollision);
	if (HealthBar)
	{
		HealthBar->DestroyComponent();
	}
	
	//调用溶解效果
	Dissolve();
	bDead = true;
	//移除异常效果组件
	BurnDebuffComponent->Deactivate();
	StunDebuffComponent->Deactivate();
	//广播角色死亡，用于一些无法监听接口，必须要通过广播接收消息 停止的组件
	OnDeathDelegate.Broadcast(this); 
}
//眩晕标签更变函数
void ABaseCharacter::StunTagChanged(const FGameplayTag CallbackTag, int32 NewCount)
{
	//判断如果为0则不需要受击反应
	bIsStunned = NewCount > 0;
	//如果被攻击 移动速度设为0,没被攻击就设回默认移速
	GetCharacterMovement()->MaxWalkSpeed = bIsStunned ? 0.f : BaseWalkSpeed;
}
//击倒标签更变函数
void ABaseCharacter::DownTagChanged(const FGameplayTag CallbackTag, int32 NewCount)
{
	//判断如果为0则不需要受击反应
	bIsDown = NewCount > 0;
	//如果被攻击 移动速度设为0,没被攻击就设回默认移速
	GetCharacterMovement()->MaxWalkSpeed = bIsDown ? 0.f : BaseWalkSpeed;
}
//蹲伏标签更变函数
void ABaseCharacter::CrouchTagChanged(const FGameplayTag CallbackTag, int32 NewCount)
{
}
//通知复制燃烧状态 给客户端
void ABaseCharacter::OnRep_Burned()
{
}

//通知复制眩晕状态 给客户端
void ABaseCharacter::OnRep_Stunned()
{
}
//通知复制击倒状态 给客户端
void ABaseCharacter::OnRep_Downed()
{
}
//通知复制蹲伏状态 给客户端
void ABaseCharacter::OnRep_Crouching()
{
}

void ABaseCharacter::BeginPlay()
{
	Super::BeginPlay();
}
//获取武器插槽位置
FVector ABaseCharacter::GetCombatSocketLocation_Implementation(const FGameplayTag& SocketTag, bool bUseFacing, float FacingDistance)
{
	// 如果使用面向，返回角色前方指定距离的位置
	if (bUseFacing)
	{
		FVector ActorLocation = GetActorLocation();
		FVector ForwardVector = GetActorForwardVector();
		return ActorLocation + (ForwardVector * FacingDistance);
	}
	
	// 原有的插槽位置逻辑
	const FBaseGameplayTags& GameplayTags = FBaseGameplayTags::Get();
	if (SocketTag.MatchesTagExact(GameplayTags.CombatSocket_Weapon) && IsValid(Weapon))
	{
		return Weapon->GetSocketLocation(WeaponTipSocketName);
	}
	else if (SocketTag.MatchesTagExact(GameplayTags.CombatSocket_LeftHand))
	{
		return GetMesh()->GetSocketLocation(LeftHandSocketName);
	}
	else if (SocketTag.MatchesTagExact(GameplayTags.CombatSocket_RightHand))
	{
		return GetMesh()->GetSocketLocation(RightHandSocketName);
	}
	else if (SocketTag.MatchesTagExact(GameplayTags.CombatSocket_Tail))
	{
		return GetMesh()->GetSocketLocation(TailSocketName);
	}
	return FVector();
}

void ABaseCharacter::InitAbilityActorInfo()
{
}

void ABaseCharacter::ApplyEffectToSelf(TSubclassOf<UGameplayEffect> GameplayEffectClass, float level) const
{
	check(IsValid(GetAbilitySystemComponent()))
	check(GameplayEffectClass)
	FGameplayEffectContextHandle ContextHandle = GetAbilitySystemComponent()->MakeEffectContext();
	//设置源对象，用于在各种计算中获取源对象 读取数据
	ContextHandle.AddSourceObject(this);
	const FGameplayEffectSpecHandle SpecHandle = GetAbilitySystemComponent()->MakeOutgoingSpec(GameplayEffectClass,level,ContextHandle);
	GetAbilitySystemComponent()->ApplyGameplayEffectSpecToTarget(*SpecHandle.Data.Get(),GetAbilitySystemComponent());
	
	
}

void ABaseCharacter::InitializeDefaultAttributes() const
{
	//初始化基础属性 把 DefaultPrimaryAttributes 赋值给 AbilitySystemComponent 能力系统组件里的数据集
	ApplyEffectToSelf(DefaultPrimaryAttributes,1.f);
	//主属性初始化完成后，初始化次要属性
	ApplyEffectToSelf(DefaultSecondaryAttributes,1.f);
	//初始化默认生命值 法力 等核心属性
	ApplyEffectToSelf(DefaultVitalAttributes,1.f);
}

void ABaseCharacter::AddCharacterAbilities()
{
	UBaseAbilitySystemComponent* BaseASC = CastChecked<UBaseAbilitySystemComponent>(AbilitySystemComponent);
	//添加能力这个操作 仅在服务器执行，所以需要先检查权限，如果没权限则直接返回
	if (!HasAuthority()) return;
	//调用 UBaseAbilitySystemComponent 组件里的添加角色能力函数
	BaseASC->AddCharacterAbilities(StartupAbilities);
	//给角色添加被动能力
	BaseASC->AddCharacterPassiveAbilities(StartupPassiveAbilities);
}
//溶解效果
void ABaseCharacter::Dissolve()
{
	//判断是否拥有溶解材质实例
	if (IsValid(DissolveMaterialInstance))
	{
		//创建动态材质实例
		UMaterialInstanceDynamic* DynamicMatInst = UMaterialInstanceDynamic::Create(DissolveMaterialInstance, this);
		//设置溶解材质实例到网格体
		GetMesh()->SetMaterial(0, DynamicMatInst);
		StartDissolveTimeline(DynamicMatInst);
	}
	//判断是否拥有武器溶解材质实例
	if (IsValid(WeaponDissolveMaterialInstance))
	{
		//创建动态材质实例
		UMaterialInstanceDynamic* DynamicMatInst = UMaterialInstanceDynamic::Create(WeaponDissolveMaterialInstance, this);
		//设置溶解材质实例到武器
		Weapon->SetMaterial(0, DynamicMatInst);
		StartWeaponDissolveTimeline(DynamicMatInst);
	}
}

 